package com.cashmate.struts;

import com.cashmate.hibernate.dao.BranchDAO;
import com.cashmate.hibernate.dao.EmployeeDAO;
import com.cashmate.hibernate.dao.UserTypeDAO;
import com.cashmate.hibernate.dao.UsertypeEmployeeDAO;
import com.cashmate.hibernate.pojo.Employees;
import com.cashmate.hibernate.pojo.UsertypeEmployee;
import com.cashmate.hibernate.pojo.Usertypes;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.log4j.Logger;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.ServletActionContext;

public class EditEmployee extends ActionSupport {

    private static Logger logger = Logger.getLogger(EditEmployee.class);
    //This properties have setters below... The setters are called and populated by the grid.
    private String oper; //add,edit,del
    private String idnumber;
    private String id;//the column in grid which we set key=true
    private String firstname;
    private String middlename;
    private String lastname;
    private String branchname; //this is not the branchname but instead it is populated with branchid
    //it is only named as such because it is name as branchname in the column in the grid
    private String type; //this is not the type of the user but instead it is populated with usertypeid
    //it is only named as such because it is nasme as type in the column in the grid
    //DAOs that extend AbstractSimpleGenericDao, see com.cashmate.dao.AbstractSimpleGenericDao.java
    private EmployeeDAO empDao = (EmployeeDAO) ServletActionContext.getServletContext().getAttribute("employeeDAO");
    private BranchDAO brDao = (BranchDAO) ServletActionContext.getServletContext().getAttribute("branchDAO");
    private UsertypeEmployeeDAO utypeEmpDao = (UsertypeEmployeeDAO) ServletActionContext.getServletContext().getAttribute("useremployeeDAO");
    private UserTypeDAO utypeDao = (UserTypeDAO) ServletActionContext.getServletContext().getAttribute("usertypeDAO");
    private Employees emps = (Employees) ServletActionContext.getRequest().getSession().getAttribute("employee");
    private Usertypes ut = (Usertypes) ServletActionContext.getRequest().getSession().getAttribute("usertype");

    //Notice we don't have a success result because we do not need to redirect the user when he/she updates the dbase
    //We redirect him/her only if an error occurred.
    @Action(value = "/edit-employee", results = {
        @Result(name = "duplicate", location = "../error/formError.jsp"),
        @Result(name = "error", type = "redirectAction", location = "../error/messages.jsp")
    })
    @Override
    public String execute() throws Exception {
        Employees emp;
        UsertypeEmployee utypeEmp;

        try {
            //oper is populated by the grid, the "add","edit","del" strings are constant values.
            if (oper.equalsIgnoreCase("add")) {
                if (branchname == null || branchname.equals("-1")) {
                    addActionError("ERROR : Please select a branch for employee " + idnumber + ".");
                    return "duplicate";
                }
                if (type == null || type.equals("-1")) {
                    addActionError("ERROR : Please select a user-type for employee " + idnumber + ".");
                    return "duplicate";
                }
                //we must get the next id of the employee to be inserted although it is auto-increment,
                //hibernate still defined the employeeid property in Employee POJO as nullable=false
                //set it's properties to whatever value in the add dialog in the grid.
                if (!empDao.hasDuplicate(idnumber)) {
                    emp = new Employees(idnumber, firstname, middlename, lastname, "newemployee", true, "new", "new");
                    emp.setBranches(brDao.get(Integer.parseInt(branchname)));
                    empDao.save(emp);

                    if (!type.equals("-1") && type != null) {
                        int uTypeId = Integer.parseInt(type);
                        utypeEmp = new UsertypeEmployee(utypeDao.get(uTypeId), emp);
                        utypeEmpDao.insert(utypeEmp);
                    }

                    logger.info(ut.getType() + " (" + emps.getIdnumber() + ") added a new Employee: {employeeid:" + id + ", idnumber:" + idnumber + ", firstname:" + firstname + ", middlename:" + middlename + ", lastname:" + lastname + ", branch:" + emp.getBranchname() + ", user-type:" + emp.getType() + "}");
                } else {
                    addActionError("ERROR : Employee " + idnumber + " already exists.");
                    return "duplicate";
                }
            } else if (oper.equalsIgnoreCase("edit")) {
                if (branchname == null || branchname.equals("-1")) {
                    addActionError("ERROR : Please select a branch for employee " + idnumber + ".");
                    return "duplicate";
                }
                if (type == null || type.equals("-1")) {
                    addActionError("ERROR : Please select a user-type for employee " + idnumber + ".");
                    return "duplicate";
                }
                int eid = Integer.parseInt(id); //Employee id because idnumber in the grid is editable.
                emp = empDao.get(eid);
                if (!emp.getIdnumber().equals(idnumber)) {
                    if (empDao.hasDuplicate(idnumber)) {
                        addActionError("ERROR : Employee " + idnumber + " already exists.");
                        return "duplicate";
                    }
                }
                String old = emp.getIdnumber();
                emp.setIdnumber(idnumber);
                emp.setFirstname(firstname);
                emp.setMiddlename(middlename);
                emp.setLastname(lastname);
                emp.setBranches(brDao.get(Integer.parseInt(branchname)));
                empDao.update(emp);

                if (!type.equals("-1") && type != null) {
                    if (emp.getUsertypeEmployeeid() == 0) {
                        int uTypeId = Integer.parseInt(type);
                        utypeEmp = new UsertypeEmployee(utypeDao.get(uTypeId), emp);
                        utypeEmpDao.insert(utypeEmp);
                    } else {
                        utypeEmp = utypeEmpDao.get(emp.getUsertypeEmployeeid());
                        //only usertype is updated because employeeid is not editable.
                        utypeEmp.setUsertypes(utypeDao.get(Integer.parseInt(type)));
                        utypeEmpDao.update(utypeEmp);
                    }
                }
                logger.info(ut.getType() + " (" + emps.getIdnumber() + ") updated Employee(" + old + ") with new values: {employeeid:" + id + ", idnumber:" + idnumber + ", firstname:" + firstname + ", middlename:" + middlename + ", lastname:" + lastname + ", branch:" + emp.getBranchname() + ", user-type:" + emp.getType() + "}");
            } else if (oper.equalsIgnoreCase("del")) {
                emp = empDao.get(Integer.parseInt(id));
                emp.setIsactive(false);
                empDao.update(emp);
                logger.info(ut.getType() + " (" + emps.getIdnumber() + ") deleted Employee(" + emp.getIdnumber() + ")");
            }
        } catch (Exception e) {
            if (emps != null) {
                logger.fatal("(" + emps.getIdnumber() + "):" + e.getLocalizedMessage(), e);
            } else {
                logger.fatal(e.getLocalizedMessage(), e);
            }
            e.printStackTrace();
            addActionError(e.getLocalizedMessage());
            return ERROR;
        }
        return NONE;
    }

    //setters
    public void setBranchname(String branchname) {
        this.branchname = branchname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public void setIdnumber(String idnumber) {
        this.idnumber = idnumber;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public void setMiddlename(String middlename) {
        this.middlename = middlename;
    }

    public void setOper(String oper) {
        this.oper = oper;
    }

    public void setType(String type) {
        this.type = type;
    }

    public void setId(String id) {
        this.id = id;
    }
}
